*/
+#include "ozi.h"
+
#include <cctype> // for tolower
#include <cmath> // for lround
#include <QChar> // for operator==, QChar
#include <QFile> // for QFile
#include <QFileInfo> // for QFileInfo
-#include <QIODevice> // for operator|, QIODevice::WriteOnly, QIODevice::ReadOnly, QIODevice, QIODevice::OpenModeFlag
-#include <QString> // for QString
+#include <QFlags> // for QFlags
+#include <QIODevice> // for operator&, QIODevice
+#include <QList> // for QList, QList<>::const_iterator
+#include <QString> // for QString, operator==
#include <QStringList> // for QStringList
+#include <QStringLiteral> // for qMakeStringPrivate, QStringLiteral
#include <QTextStream> // for QTextStream, operator<<, qSetRealNumberPrecision, QTextStream::FixedNotation
-#include <QVector> // for QVector
#include <Qt> // for CaseInsensitive
#include <QtGlobal> // for qPrintable
#include "defs.h"
#include "csv_util.h" // for csv_stringclean
-#include "formspec.h" // for FsChainAdd, FsChainFind, kFsOzi, FormatSpecificData
-#include "jeeps/gpsmath.h" // for GPS_Math_Known_Datum_To_WGS84_M
+#include "formspec.h" // for FormatSpecificDataList, kFsOzi
+#include "jeeps/gpsmath.h" // for GPS_Lookup_Datum_Index, GPS_Math_Known_Datum_To_WGS84_M
#include "mkshort.h" // for MakeShort
#include "src/core/datetime.h" // for DateTime
#include "src/core/textstream.h" // for TextStream
#define BADCHARS ",\r\n"
#define DAYS_SINCE_1990 25569
-struct ozi_fsdata : FormatSpecificData {
- ozi_fsdata() : FormatSpecificData(kFsOzi) {}
-
- ozi_fsdata* clone() const override
- {
- return new ozi_fsdata(*this);
- }
-
- int fgcolor{0};
- int bgcolor{65535};
-};
-
-static gpsbabel::TextStream* stream = nullptr;
-
-static MakeShort* mkshort_handle;
-static route_head* trk_head;
-static route_head* rte_head;
-
-static int track_out_count;
-static int route_out_count;
-static int route_wpt_count;
-static int new_track;
-
-static char* snlenopt = nullptr;
-static char* snwhiteopt = nullptr;
-static char* snupperopt = nullptr;
-static char* snuniqueopt = nullptr;
-static char* wptfgcolor = nullptr;
-static char* wptbgcolor = nullptr;
-static char* pack_opt = nullptr;
-static int datum;
-static char* proximityarg = nullptr;
-static double proximity;
-static char* altunit_opt;
-static char* proxunit_opt;
-static char altunit;
-static char proxunit;
-static double alt_scale;
-static double prox_scale;
-static char* opt_codec;
-
-static
-QVector<arglist_t> ozi_args = {
- {
- "pack", &pack_opt, "Write all tracks into one file",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "snlen", &snlenopt, "Max synthesized shortname length",
- "32", ARGTYPE_INT, "1", nullptr, nullptr
- },
- {
- "snwhite", &snwhiteopt, "Allow whitespace synth. shortnames",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "snupper", &snupperopt, "UPPERCASE synth. shortnames",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "snunique", &snuniqueopt, "Make synth. shortnames unique",
- nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
- },
- {
- "wptfgcolor", &wptfgcolor, "Waypoint foreground color",
- "black", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
- {
- "wptbgcolor", &wptbgcolor, "Waypoint background color",
- "yellow", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
- {
- "proximity", &proximityarg, "Proximity distance",
- "0", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
- {
- "altunit", &altunit_opt, "Unit used in altitude values",
- "feet", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
- {
- "proxunit", &proxunit_opt, "Unit used in proximity values",
- "miles", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
- {
- "codec", &opt_codec, "codec to use for reading and writing strings (default windows-1252)",
- "windows-1252", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
- },
-};
-
-static gpsdata_type ozi_objective;
-
-static QString ozi_ofname;
-
-static void
-ozi_open_io(const QString& fname, QIODevice::OpenModeFlag mode)
+void
+OziFormat::ozi_open_io(const QString& fname, QIODevice::OpenModeFlag mode)
{
stream = new gpsbabel::TextStream;
stream->open(fname, mode, MYNAME, opt_codec);
}
}
-static void
-ozi_close_io()
+void
+OziFormat::ozi_close_io()
{
if (!stream) {
return;
stream = nullptr;
}
-static
-ozi_fsdata*
-ozi_alloc_fsdata()
+OziFormat::ozi_fsdata*
+OziFormat::ozi_alloc_fsdata()
{
auto* fsdata = new ozi_fsdata;
return fsdata;
}
-static QString
-ozi_get_time_str(const Waypoint* waypointp)
+QString
+OziFormat::ozi_get_time_str(const Waypoint* waypointp)
{
if (waypointp->creation_time.isValid()) {
double time = (waypt_time(waypointp) / SECONDS_PER_DAY) + DAYS_SINCE_1990;
return QString("");
}
-static void
-ozi_set_time_str(const QString& str, Waypoint* waypointp)
+void
+OziFormat::ozi_set_time_str(const QString& str, Waypoint* waypointp)
{
double ozi_time = str.toDouble();
}
}
-static void
-ozi_convert_datum(Waypoint* wpt)
+void
+OziFormat::ozi_convert_datum(Waypoint* wpt) const
{
if (datum != kDautmWGS84) {
double lat, lon, alt;
}
}
-static void
-ozi_openfile(const QString& fname)
+void
+OziFormat::ozi_openfile(const QString& fname)
{
const char* ozi_extensions[] = {nullptr, "plt", "wpt", "rte"};
ozi_open_io(tmpname, QFile::WriteOnly);
}
-static void
-ozi_track_hdr(const route_head* rte)
+void
+OziFormat::ozi_track_hdr(const route_head* rte)
{
if ((! pack_opt) || (track_out_count == 0)) {
ozi_openfile(ozi_ofname);
new_track = 1;
}
-static void
-ozi_track_disp(const Waypoint* waypointp)
+void
+OziFormat::ozi_track_disp(const Waypoint* waypointp)
{
double alt;
new_track = 0;
}
-static void
-ozi_track_pr()
+void
+OziFormat::ozi_track_pr()
{
- track_disp_all(ozi_track_hdr, nullptr, ozi_track_disp);
+ auto ozi_track_hdr_lambda = [this](const route_head* rte)->void {
+ ozi_track_hdr(rte);
+ };
+ auto ozi_track_disp_lambda = [this](const Waypoint* waypointp)->void {
+ ozi_track_disp(waypointp);
+ };
+ track_disp_all(ozi_track_hdr_lambda, nullptr, ozi_track_disp_lambda);
}
-static void
-ozi_route_hdr(const route_head* rte)
+void
+OziFormat::ozi_route_hdr(const route_head* rte)
{
/* prologue on 1st pass only */
if (route_out_count == 0) {
<< rte->rte_desc << ",\r\n";
}
-static void
-ozi_route_disp(const Waypoint* waypointp)
+void
+OziFormat::ozi_route_disp(const Waypoint* waypointp)
{
route_wpt_count++;
}
-static void
-ozi_route_pr()
+void
+OziFormat::ozi_route_pr()
{
- route_disp_all(ozi_route_hdr, nullptr, ozi_route_disp);
+ auto ozi_route_hdr_lambda = [this](const route_head* rte)->void {
+ ozi_route_hdr(rte);
+ };
+ auto ozi_route_disp_lambda = [this](const Waypoint* waypointp)->void {
+ ozi_route_disp(waypointp);
+ };
+ route_disp_all(ozi_route_hdr_lambda, nullptr, ozi_route_disp_lambda);
}
-static void
-ozi_init_units(const int direction) /* 0 = in; 1 = out */
+void
+OziFormat::ozi_init_units(const int direction) /* 0 = in; 1 = out */
{
altunit = tolower(*altunit_opt);
switch (altunit) {
}
}
-static void
-rd_init(const QString& fname)
+void
+OziFormat::rd_init(const QString& fname)
{
ozi_open_io(fname, QFile::ReadOnly);
ozi_init_units(0);
}
-static void
-rd_deinit()
+void
+OziFormat::rd_deinit()
{
ozi_close_io();
}
-static void
-wr_init(const QString& fname)
+void
+OziFormat::wr_init(const QString& fname)
{
/* At this point, we have no idea whether we'll be writing waypoint,
parse_distance(proximityarg, &proximity, 1 / prox_scale, MYNAME);
}
-static void
-wr_deinit()
+void
+OziFormat::wr_deinit()
{
ozi_close_io();
ozi_ofname.clear();
mkshort_handle = nullptr;
}
-static void
-ozi_parse_waypt(int field, const QString& str, Waypoint* wpt_tmp, ozi_fsdata* fsdata)
+void
+OziFormat::ozi_parse_waypt(int field, const QString& str, Waypoint* wpt_tmp, ozi_fsdata* fsdata) const
{
double alt;
}
}
-static void
-ozi_parse_track(int field, const QString& str, Waypoint* wpt_tmp, char* trk_name)
+void
+OziFormat::ozi_parse_track(int field, const QString& str, Waypoint* wpt_tmp, char* trk_name)
{
if (str.isEmpty()) {
return;
}
}
-static void
-ozi_parse_routepoint(int field, const QString& str, Waypoint* wpt_tmp)
+void
+OziFormat::ozi_parse_routepoint(int field, const QString& str, Waypoint* wpt_tmp)
{
if (str.isEmpty()) {
return;
}
}
-static void
-ozi_parse_routeheader(int field, const QString& str)
+void
+OziFormat::ozi_parse_routeheader(int field, const QString& str)
{
switch (field) {
}
}
-static void
-data_read()
+void
+OziFormat::read()
{
QString buff;
char* trk_name = nullptr;
}
}
-static void
-ozi_waypt_pr(const Waypoint* wpt)
+void
+OziFormat::ozi_waypt_pr(const Waypoint* wpt, int index)
{
- static int index = 0;
double alt;
QString description;
QString shortname;
description = csv_stringclean(wpt->description, BADCHARS);
}
- index++;
-
if (wpt->icon_descr.toInt()) {
icon = wpt->icon_descr.toInt();
}
}
}
-static void
-data_write()
+void
+OziFormat::write()
{
if (waypt_count()) {
track_out_count = route_out_count = 0;
<< "WGS 84\r\n"
<< "Reserved 2\r\n"
<< "Reserved 3\r\n";
- waypt_disp_all(ozi_waypt_pr);
+
+ int index = 0;
+ auto ozi_waypt_pr_lambda = [this, &index](const Waypoint* waypointp)->void {
+ ozi_waypt_pr(waypointp, ++index);
+ };
+ waypt_disp_all(ozi_waypt_pr_lambda);
}
if (track_count()) {
}
}
-
-ff_vecs_t ozi_vecs = {
- ff_type_file,
- FF_CAP_RW_ALL,
- rd_init,
- wr_init,
- rd_deinit,
- wr_deinit,
- data_read,
- data_write,
- nullptr,
- &ozi_args,
- NULL_POS_OPS
-};
--- /dev/null
+/*
+ OziExplorer Waypoints/Tracks/Routes
+ Comma Delimited
+
+ As described in OziExplorer Help File
+
+ Copyright (C) 2002-2005 Robert Lipe, robertlipe+source@gpsbabel.org
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+ Reference:
+ https://www.oziexplorer4.com/eng/help/fileformats.html
+
+ According to the OZI Explorer developer:
+ "There is no specified character set, it defaults to whatever 8 bit
+ character set "Windows" defaults to - normally CP-1252 but can vary
+ depending on Windows regional settings."
+
+ According to the reference, for some text fields:
+ "comma's not allowed in text fields, character 209 can be used instead
+ and a comma will be substituted."
+ This could work for windows-1252, but not for utf-8.
+ We don't support any special handling for character 209.
+
+ */
+#ifndef OZI_H_INCLUDED_
+#define OZI_H_INCLUDED_
+
+#include <QIODevice> // for QIODeviceBase, QIODeviceBase::OpenModeFlag
+#include <QString> // for QString
+#include <QVector> // for QVector
+
+#include "defs.h"
+#include "format.h" // for Format
+#include "formspec.h" // for FormatSpecificData, kFsOzi
+#include "mkshort.h" // for MakeShort
+#include "src/core/textstream.h" // for TextStream
+
+
+class OziFormat : public Format
+{
+public:
+ QVector<arglist_t>* get_args() override
+ {
+ return &ozi_args;
+ }
+
+ ff_type get_type() const override
+ {
+ return ff_type_file;
+ }
+
+ QVector<ff_cap> get_cap() const override
+ {
+ return FF_CAP_RW_ALL;
+ }
+
+ void rd_init(const QString& fname) override;
+ void read() override;
+ void rd_deinit() override;
+ void wr_init(const QString& fname) override;
+ void write() override;
+ void wr_deinit() override;
+
+private:
+ /* Types */
+
+ struct ozi_fsdata : FormatSpecificData {
+ ozi_fsdata() : FormatSpecificData(kFsOzi) {}
+
+ ozi_fsdata* clone() const override
+ {
+ return new ozi_fsdata(*this);
+ }
+
+ int fgcolor{0};
+ int bgcolor{65535};
+ };
+
+ /* Member Functions */
+
+ void ozi_open_io(const QString& fname, QIODevice::OpenModeFlag mode);
+ void ozi_close_io();
+ ozi_fsdata* ozi_alloc_fsdata();
+ static QString ozi_get_time_str(const Waypoint* waypointp);
+ static void ozi_set_time_str(const QString& str, Waypoint* waypointp);
+ void ozi_convert_datum(Waypoint* wpt) const;
+ void ozi_openfile(const QString& fname);
+ void ozi_track_hdr(const route_head* rte);
+ void ozi_track_disp(const Waypoint* waypointp);
+ void ozi_track_pr();
+ void ozi_route_hdr(const route_head* rte);
+ void ozi_route_disp(const Waypoint* waypointp);
+ void ozi_route_pr();
+ void ozi_init_units(int direction);
+ void ozi_parse_waypt(int field, const QString& str, Waypoint* wpt_tmp, ozi_fsdata* fsdata) const;
+ void ozi_parse_track(int field, const QString& str, Waypoint* wpt_tmp, char* trk_name);
+ static void ozi_parse_routepoint(int field, const QString& str, Waypoint* wpt_tmp);
+ void ozi_parse_routeheader(int field, const QString& str);
+ void data_read();
+ void ozi_waypt_pr(const Waypoint* wpt, int index);
+ void data_write();
+
+ /* Data Members */
+
+ gpsbabel::TextStream* stream = nullptr;
+
+ MakeShort* mkshort_handle{};
+ route_head* trk_head{};
+ route_head* rte_head{};
+
+ int track_out_count{};
+ int route_out_count{};
+ int route_wpt_count{};
+ int new_track{};
+
+ char* snlenopt = nullptr;
+ char* snwhiteopt = nullptr;
+ char* snupperopt = nullptr;
+ char* snuniqueopt = nullptr;
+ char* wptfgcolor = nullptr;
+ char* wptbgcolor = nullptr;
+ char* pack_opt = nullptr;
+ int datum{};
+ char* proximityarg = nullptr;
+ double proximity{};
+ char* altunit_opt{};
+ char* proxunit_opt{};
+ char altunit{};
+ char proxunit{};
+ double alt_scale{};
+ double prox_scale{};
+ char* opt_codec{};
+
+ QVector<arglist_t> ozi_args = {
+ {
+ "pack", &pack_opt, "Write all tracks into one file",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "snlen", &snlenopt, "Max synthesized shortname length",
+ "32", ARGTYPE_INT, "1", nullptr, nullptr
+ },
+ {
+ "snwhite", &snwhiteopt, "Allow whitespace synth. shortnames",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "snupper", &snupperopt, "UPPERCASE synth. shortnames",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "snunique", &snuniqueopt, "Make synth. shortnames unique",
+ nullptr, ARGTYPE_BOOL, ARG_NOMINMAX, nullptr
+ },
+ {
+ "wptfgcolor", &wptfgcolor, "Waypoint foreground color",
+ "black", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+ {
+ "wptbgcolor", &wptbgcolor, "Waypoint background color",
+ "yellow", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+ {
+ "proximity", &proximityarg, "Proximity distance",
+ "0", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+ {
+ "altunit", &altunit_opt, "Unit used in altitude values",
+ "feet", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+ {
+ "proxunit", &proxunit_opt, "Unit used in proximity values",
+ "miles", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+ {
+ "codec", &opt_codec, "codec to use for reading and writing strings (default windows-1252)",
+ "windows-1252", ARGTYPE_STRING, ARG_NOMINMAX, nullptr
+ },
+ };
+
+ gpsdata_type ozi_objective{unknown_gpsdata};
+
+ QString ozi_ofname;
+};
+#endif // OZI_H_INCLUDED_